//------------------------------------------------------------------------------
// The confidential and proprietary information contained in this file may
// only be used by a person authorised under and to the extent permitted
// by a subsisting licensing agreement from ARM Limited.
//
//            (C) COPYRIGHT 2012 ARM Limited.
//                ALL RIGHTS RESERVED
//
// This entire notice must be reproduced on all copies of this file
// and copies of this file may only be made by a person if such person is
// permitted to do so under the terms of a subsisting license agreement
// from ARM Limited.
//------------------------------------------------------------------------------
//  Version and Release Control Information:
//
//  File Revision       : 132916
//
//  Date                :  2012-07-02 13:38:10 +0100 (Mon, 02 Jul 2012)
//
//  Release Information : PL401-r0p1-00eac0
//
//------------------------------------------------------------------------------
//  File Purpose        : Transaction tracker to maintain status of
//                        outstanding transcations for a slave interface
//                        and to ensure that no cyclic dependency deadlocks
//                        can occur.
//   
//  Key Configuration Details-
//      - No CDAS 
//      - Acceptance capability 1
//      - Number of connected master interfaces 4
//   
// Notes on port naming conventions- 
//
//     All AXI point to point connections can be considered a 
//     MasterInterface - SlaveInterface connection. 
//
//     The AXI ports on the NIC400 A3BM are named as follows-  
//
//     *_m<n> suffix to denote a MasterInterface (connect to external AXI slave)
//     *_s0 suffix to denote the SlaveInterface  (connect to external AXI master) 
//
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Module Declaration
//------------------------------------------------------------------------------



module nic400_switch2_rd_st_tt_s1_ysyx_rv32
  (
    tt_enable,

    asel,
    aready,
    resp_valid,
    resp_last,
    resp_ready,

    // Miscelaneous connections
    aclk,
    aresetn
  );

  // ---------------------------------------------------------------------------
  //  parameters
  // ---------------------------------------------------------------------------

  // ---------------------------------------------------------------------------
  //  Port definitions
  // ---------------------------------------------------------------------------
    output [3:0]    tt_enable;     // Enable for the selected return channel

    input  [3:0]    asel;     // Selected address channel
    input        aready;
    input        resp_valid;
    input        resp_last;
    input        resp_ready;
    // Miscelaneous connections
    input        aclk;
    input        aresetn;

  //----------------------------------------------------------------------------
  // Wires 
  //----------------------------------------------------------------------------

  reg            next_tt_cnt;    // next transaction tracker value
  wire           tt_reg_enable;    // Enable for transaction counter
  wire           next_resp_stall;    // next resp stall to ensure sticky valid
  reg   [3:0]    reg_tt_en;     // registered return channel select
  wire  [3:0]    next_tt_reg;    // next selected master interface
  wire  [3:0]    int_tt_en;     // Enable for the selected return channel


  //----------------------------------------------------------------------------
  // Registers 
  //----------------------------------------------------------------------------

  reg            resp_stall;    // resp stall to ensure sticky valid
  reg   [3:0]    tt_reg;    // Selected master interface
  reg            tt_cnt;    // outstanding transaction counter


  // ---------------------------------------------------------------------------
  //  start of code
  // ---------------------------------------------------------------------------

   //---------------------------- Combinatorial logic --------------------------


   // Count the number of outstanding transactions
   always @(asel or aready or resp_valid or resp_last or resp_ready or tt_cnt)
     begin : p_next_tt_comb
        next_tt_cnt = tt_cnt;
        if ((|asel && aready) && !(resp_valid && resp_last && resp_ready)) begin
                next_tt_cnt = tt_cnt + 1'b1;
        end
        if (!(|asel && aready) && (resp_valid && resp_last && resp_ready)) begin
                next_tt_cnt = tt_cnt - 1'b1;
        end
     end // p_next_tt_comb


  // Determine next selected destination
   assign next_tt_reg = (|asel && aready) ? asel 
                        : (next_tt_cnt == 1'b0) ? {4{1'b0}}
                        : tt_reg;

   assign tt_reg_enable = ((|asel && aready)
                           || (resp_valid && resp_last && resp_ready));

  //---------------------------- Sequential logic -----------------------------


   always @(posedge aclk or negedge aresetn)
     begin : p_tt_seq
       if (!aresetn) 
         begin
                tt_reg <= {4{1'b0}};
                tt_cnt <= 1'b0;
         end
       else if (tt_reg_enable)
         begin
                tt_reg <= next_tt_reg;
                tt_cnt <= next_tt_cnt;
         end
     end // end p_tt_seq
  //---------------------------- Output Enables -------------------------------

   assign next_resp_stall = (resp_valid & ~resp_ready);

   always @(posedge aclk or negedge aresetn)
     begin : p_stall_seq
       if (!aresetn)
         begin
          resp_stall <= 1'b0;
        end
       else
         begin
          resp_stall <= next_resp_stall;
        end
     end // p_stall_seq

 
   assign int_tt_en = tt_reg;
 

   always @(posedge aclk or negedge aresetn)
     begin : p_tt_en_seq
       if (!aresetn)
         begin
          reg_tt_en <= {4{1'b0}};
        end
       else if (next_resp_stall && !resp_stall)
         begin
          reg_tt_en <= int_tt_en;
        end
     end // p_tt_en_seq
 
   assign tt_enable = resp_stall ? reg_tt_en : int_tt_en;

//------------------------------------------------------------------------------
// OVL Assertions
//------------------------------------------------------------------------------
// synopsys translate_off

`ifdef ARM_ASSERT_ON


assign dec_from_zero = (tt_cnt==2'b00) & resp_valid & resp_ready;

assert_never #(1,0,"ERROR, Transaction Counter decrementing from 0")
ovl_assert_dec_empty
   (
    .clk       (aclk),
    .reset_n   (aresetn),
    .test_expr (dec_from_zero));

assign inc_from_full = (tt_cnt==1'b1) & |asel & aready;

assert_never #(1,0,"ERROR, Transaction Counter incrementing when full")
ovl_assert_inc_full
   (
    .clk       (aclk),
    .reset_n   (aresetn),
    .test_expr (inc_from_full));


`endif
// synopsys translate_on

  endmodule

//  --=============================== End ====================================--
